#ifndef __M_CONSUMER_H__
#define __M_CONSUMER_H__
#include "../mqcommon/mq_logger.hpp"
#include "../mqcommon/mq_helper.hpp"
#include "../mqcommon/mq_msg.pb.h"
#include <iostream>
#include <unordered_map>
#include <mutex>
#include <functional>
#include <vector>

namespace mymq
{
    // 消费者收到消息后调用回调函数处理，消费者标识-消息属性-消息主体
    using ConsumerCallback = std::function<void(const std::string, const BasicProperties* bp, const std::string)>;
    struct Consumer
    {
        using ptr = std::shared_ptr<Consumer>;
        std::string tag; // 消费者标识
        std::string qname; // 消费者订阅的队列名称
        bool auto_ack; // 是否自动确认标识
        ConsumerCallback callback;

        Consumer()
        {
            DLOG("new consumer %p", this);
        }
        Consumer(const std::string& ctag, const std::string& queue_name, bool ack_tag, 
            const ConsumerCallback& cb)
        : tag(ctag), qname(queue_name), auto_ack(ack_tag), callback(cb)
        {
            DLOG("new consumer %p", this);
        }
        ~Consumer()
        {
            DLOG("del consumer %p", this);
        }
    };

    class QueueConsumer
    {
    public:
        using ptr = std::shared_ptr<QueueConsumer>;
        QueueConsumer(const std::string& qname)
        : _qname(qname), _RR_seq(0)
        {}

        // 队列新增消费者
        Consumer::ptr create(const std::string& ctag, const std::string& queue_name, bool ack_tag, 
            const ConsumerCallback& cb)
        {
            std::unique_lock<std::mutex> lock(_mutex);

            // 遍历数组 查找消费者是否已经存在
            for (auto& consumer : _consumers)
            {
                if (consumer->tag == ctag)
                    return Consumer::ptr();
            }

            // 不存在，构造消费者对象
            Consumer::ptr consumer = std::make_shared<Consumer>(ctag, queue_name, ack_tag, cb);
            _consumers.push_back(consumer);
            return consumer;
        }
        // 队列移除消费者
        void remove(const std::string& ctag)
        {
            std::unique_lock<std::mutex> lock(_mutex);

            // 遍历数组 有就删除
            for (auto it = _consumers.begin(); it != _consumers.end(); it++)
            {
                if ((*it)->tag == ctag)
                {
                    _consumers.erase(it);
                    return;
                }
            }
        }
        // 轮询获取一个消费者
        Consumer::ptr choose()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            if (_consumers.size() == 0) return Consumer::ptr();

            // 获取轮询序号
            int idx = _RR_seq % _consumers.size();
            ++_RR_seq;

            // 返回
            return _consumers[idx];
        }

        // test
        // 消费者队列是否为空
        bool empty()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            return _consumers.empty();
        }
        // 查看指定消费者是否存在
        bool exists(const std::string& ctag)
        {
            std::unique_lock<std::mutex> lock(_mutex);

            // 遍历数组 查找消费者是否已经存在
            for (auto& consumer : _consumers)
            {
                if (consumer->tag == ctag)
                    return true;
            }
            return false;
        }
        // 清理
        void clear()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _RR_seq = 0;
            _consumers.clear();
        }
    private:
        std::mutex _mutex;
        std::string _qname; // 队列名
        uint64_t _RR_seq; // 轮转序号
        // 采用 vector 管理消费者，方便使用下标访问，实现轮询获取消费者
        std::vector<Consumer::ptr> _consumers;
    };

    class ConsumerManager
    {
    public:
        using ptr = std::shared_ptr<ConsumerManager>;
        ConsumerManager() {}

        // 初始化队列的消费者结构
        void initQueueConsumer(const std::string& qname)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            // 查看是否已经存在
            auto it = _queue_consumers.find(qname);
            if (it != _queue_consumers.end())
                return; // 已经存在

            // 不存在，创建
            QueueConsumer::ptr qcp = std::make_shared<QueueConsumer>(qname);
            _queue_consumers.insert(std::make_pair(qname, qcp));
        }

        // 销毁队列的消费者结构
        void destroyQueueConsumer(const std::string& qname)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _queue_consumers.erase(qname);
        }

        // 队列新增消费者
        Consumer::ptr create(const std::string& ctag, const std::string& queue_name, bool ack_tag, 
            const ConsumerCallback& cb)
        {
            QueueConsumer::ptr qcp;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                // 查看 队列消费者 管理句柄是否存在
                auto it = _queue_consumers.find(queue_name);
                if (it == _queue_consumers.end())
                {
                    DLOG("队列 %s 新增消费者失败：无法找到队列消费者管理句柄！", queue_name.c_str());
                    return Consumer::ptr();
                }
                qcp = it->second;
            }
            return qcp->create(ctag, queue_name, ack_tag, cb);
        }

        // 删除队列中消费者
        void remove(const std::string& ctag, const std::string& queue_name)
        {
            QueueConsumer::ptr qcp;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                // 查看 队列消费者 管理句柄是否存在
                auto it = _queue_consumers.find(queue_name);
                if (it == _queue_consumers.end())
                {
                    DLOG("队列 %s 删除消费者 %s 失败：无法找到队列消费者管理句柄！", queue_name.c_str(), ctag.c_str());
                    return;
                }
                qcp = it->second;
            }
            qcp->remove(ctag);
        }

        // 获取某队列消费者
        Consumer::ptr choose(const std::string& queue_name)
        {
            QueueConsumer::ptr qcp;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                // 查看 队列消费者 管理句柄是否存在
                auto it = _queue_consumers.find(queue_name);
                if (it == _queue_consumers.end())
                {
                    DLOG("获取队列 %s 消费者失败：无法找到队列消费者管理句柄！", queue_name.c_str());
                    return Consumer::ptr();
                }
                qcp = it->second;
            }
            return qcp->choose();
        }

        // test
        bool empty(const std::string& queue_name)
        {
            QueueConsumer::ptr qcp;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                // 查看 队列消费者 管理句柄是否存在
                auto it = _queue_consumers.find(queue_name);
                if (it == _queue_consumers.end())
                {
                    DLOG("队列 %s 判空失败：无法找到队列消费者管理句柄！", queue_name.c_str());
                    return false;
                }
                qcp = it->second;
            }
            return qcp->empty();
        }

        bool exists(const std::string& ctag, const std::string& queue_name)
        {
            QueueConsumer::ptr qcp;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                // 查看 队列消费者 管理句柄是否存在
                auto it = _queue_consumers.find(queue_name);
                if (it == _queue_consumers.end())
                {
                    DLOG("判断队列 %s 中某消费者是否存在失败：无法找到队列消费者管理句柄！", queue_name.c_str());
                    return false;
                }
                qcp = it->second;
            }
            return qcp->exists(ctag);
        }

        void clear()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _queue_consumers.clear();
        }

    private:
        std::mutex _mutex;
        std::unordered_map<std::string, QueueConsumer::ptr> _queue_consumers;
    };
}

#endif